package com.ccp.dev.form.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.internationalization.LocaleMessageSource;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.*;
import com.ccp.dev.form.consts.FormConstants;
import com.ccp.dev.form.dao.*;
import com.ccp.dev.form.model.*;
import com.ccp.dev.form.util.PlatformType;
import com.ccp.dev.form.xml.form.BpmFormDefXml;
import com.ccp.dev.form.xml.form.BpmFormDefXmlList;
import com.ccp.dev.form.xml.table.BpmFormTableXml;
import com.ccp.dev.form.xml.util.MsgUtil;
import com.ccp.dev.system.dao.*;
import com.ccp.dev.system.model.*;
import com.ccp.dev.workflow.model.Identity;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.system.service.SysTenantDynamicDataService;
import com.ccp.dev.workflow.model.BpmNodeSet;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.util.JSONUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;


/**
 * BPM_FORM_DEF service类
 *
 * @author zhaowj
 */
@Service
public class FormDefService extends BaseService<FormDef> {

    @Resource
    FormDefDao formDefDao;

    @Resource
    FormTableService formTableService;

    @Resource
    FormFieldService formFieldService;

    @Resource
    DataTemplateDao dataTemplateDao;

    @Resource
    FormRightsDao formRightsDao;

    @Resource
    SysBusEventDao sysBusEventDao;

    @Resource
    FormDefTreeDao formDefTreeDao;

    @Resource
    SysTenantDynamicDataService sysTenantDynamicDataService;

    @Resource
    FormRightsService formRightsService;

    @Resource
    GlobalTypeDao globalTypeDao;
    @Resource
    private SysUserDao sysUserDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private SysOrgDao  sysOrgDao;
    @Resource
    private PositionDao positionDao;

    @Resource
    protected LocaleMessageSource localeMessageSource;

    @Resource
    protected SysHistoryDataService historyDataService;
    @Resource
    protected DataTemplateService dataTemplateService;

    /**
     * 判断自定义表是否绑定了表单
     *
     * @param tableId 自定义表ID
     * @return true 绑定了表单
     * false 末绑定表单
     */
    public boolean isTableBindForm(String tableId) {
        int count = formDefDao.isTableBindForm(tableId);
        return count > 0;
    }

    /**
     * 获得表是否有数据。
     *
     * @param table Map
     * @return true有数据，false没数据
     */
    public boolean isTableHasData(Map table) {
        int result = formDefDao.isTableHasData(table);
        return result > 0;
    }

    /**
     * 导出表单XML
     *
     * @param formDefIds 表单ids
     * @param map        是否导出的Map列表
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public String exportXml(String[] formDefIds, Map<String, Boolean> map) throws Exception {
        BpmFormDefXmlList bpmFormDefXmlList = new BpmFormDefXmlList();
        List<BpmFormDefXml> list = new ArrayList<>();
        for (int i = 0; i < formDefIds.length; i++) {
            FormDef bpmFormDef = formDefDao.getById(formDefIds[i]);
            String tenantId = ContextUtil.getCurrentUserTenantId();
            bpmFormDef.setTenant(tenantId);
            BpmFormDefXml bpmFormDefXml = exportBpmFormDef(bpmFormDef, FormDef.IS_DEFAULT, map);
            list.add(bpmFormDefXml);
        }
        bpmFormDefXmlList.setBpmFormDefXmlList(list);
        return XmlBeanUtil.marshall(bpmFormDefXmlList, BpmFormDefXmlList.class);
    }

    /**
     * 导出表单的信息
     *
     * @param bpmFormDef 表单
     * @param isDefault  是否是默认 默认则要导出其它表单和模板
     * @param map        是否导出的Map列表
     * @return BpmFormDefXml
     */
    public BpmFormDefXml exportBpmFormDef(FormDef bpmFormDef, Short isDefault, Map<String, Boolean> map) {
        BpmFormDefXml bpmFormDefXml = new BpmFormDefXml();
        // 表单
        bpmFormDefXml.setBpmFormDef(bpmFormDef);
        String formKey = bpmFormDef.getFormKey();
        if (isDefault.shortValue() == FormDef.IS_DEFAULT.shortValue()) {
            // 导出对应的表
            if (map.get(FormConstants.STR_BPM_FORM_TABLE)) {
                exportBpmFormTableXml(bpmFormDef, bpmFormDefXml);
            }
            if (StringUtil.isNotEmpty(formKey)) {
                // 导出其它版本的自定义表单 非默认版本
                if (map.get(FormConstants.STR_FORM_DEF_OTHER)) {
                    exportBpmFormDefOther(formKey, map, bpmFormDefXml);
                }
                // 数据模板
                if (map.get(FormConstants.STR_TABLE_TEMPLATE)) {
                    exportBpmDataTemplate(formKey, bpmFormDefXml);
                }
            }
        }
        // 导出表单权限
        if (map.get(FormConstants.STR_FORM_RIGHTS)) {
            exportBpmFormRights(formKey, bpmFormDefXml);
        }
        //导出业务数据
        if (map.get(FormConstants.STR_SYS_BUS_EVENT)) {
            exportSysBusEvent(formKey, bpmFormDefXml);
        }
        //导出表单树形配置
        if (map.get(FormConstants.STR_FORM_DEF_TREE)) {
            exportFormDefTree(formKey, bpmFormDefXml);
        }
        return bpmFormDefXml;
    }

    /**
     * 导出对应的表
     *
     * @param bpmFormDef    FormDef
     * @param bpmFormDefXml BpmFormDefXml
     */
    private void exportBpmFormTableXml(FormDef bpmFormDef, BpmFormDefXml bpmFormDefXml) {
        if (StringUtil.isEmpty(bpmFormDef.getTableId())) {
            return;
        }
        if (StringUtil.isEmpty(bpmFormDef.getTableId()) && bpmFormDef.getDesignType() == FormDef.DESIGN_TYPE_CUSTOM_DESIGN) {
            return;
        }
        FormTable formTable = formTableService.getOneById(bpmFormDef.getTableId());
        BpmFormTableXml bpmFormTableXml = formTableService.exportTable(formTable, null);
        bpmFormDefXml.setBpmFormTableXml(bpmFormTableXml);
    }

    /**
     * 导出其它版本的自定义表单
     *
     * @param formKey       表单别名
     * @param map           Map<String, Boolean>
     * @param bpmFormDefXml BpmFormDefXml
     */
    private void exportBpmFormDefOther(String formKey, Map<String, Boolean> map, BpmFormDefXml bpmFormDefXml) {
        List<FormDef> formDefList = formDefDao.getByFormKeyIsDefault(formKey, FormDef.IS_NOT_DEFAULT);
        if (BeanUtils.isEmpty(formDefList)) {
            return;
        }
        List<BpmFormDefXml> list = new ArrayList<>();
        for (FormDef formDef : formDefList) {
            BpmFormDefXml formDefXml = exportBpmFormDef(formDef, FormDef.IS_NOT_DEFAULT, map);
            list.add(formDefXml);
        }
        bpmFormDefXml.setBpmFormDefXmlList(list);
    }

    /**
     * 导出数据模板
     *
     * @param formKey       自定义表单key
     * @param bpmFormDefXml BpmFormDefXml
     */
    private void exportBpmDataTemplate(String formKey, BpmFormDefXml bpmFormDefXml) {
        DataTemplate bpmDataTemplate = dataTemplateDao.getByFormKey(formKey);
        if (BeanUtils.isNotEmpty(bpmDataTemplate)) {
            bpmFormDefXml.setBpmDataTemplate(bpmDataTemplate);
        }
    }

    /**
     * 导出表单权限
     *
     * @param formKey       自定义表单key
     * @param bpmFormDefXml BpmFormDefXml
     */
    private void exportBpmFormRights(String formKey, BpmFormDefXml bpmFormDefXml) {
        List<FormRights> bpmFormRightsList = formRightsDao.getByFormKeyNodeEmpty(formKey);
        if (BeanUtils.isNotEmpty(bpmFormRightsList)) {
            bpmFormDefXml.setBpmFormRightsList(bpmFormRightsList);
        }
    }

    /**
     * 处理人员
     * @param formRightsList
     * @return
     */
    public List<FormRights> exportFormRightsUser(List<FormRights> formRightsList) {
        List<FormRights> formRightsArrayList = new ArrayList<FormRights>();
        // 处理人员
        for (FormRights formRights : formRightsList) {
            String permission = formRights.getPermission();
            formRights.setPermission(parsePermission(permission, true));
            formRightsArrayList.add(formRights);
        }
        return formRightsArrayList;
    }

    /**
     * 导出业务保存设置
     *
     * @param formKey       自定义表单key
     * @param bpmFormDefXml BpmFormDefXml
     */
    private void exportSysBusEvent(String formKey, BpmFormDefXml bpmFormDefXml) {
        SysBusEvent sysBusEvent = sysBusEventDao.getByFormKey(formKey);
        if (BeanUtils.isNotEmpty(sysBusEvent)) {
            bpmFormDefXml.setSysBusEvent(sysBusEvent);
        }
    }

    /**
     * 导出表单树
     *
     * @param formKey       自定义表单key
     * @param bpmFormDefXml BpmFormDefXml
     */
    private void exportFormDefTree(String formKey, BpmFormDefXml bpmFormDefXml) {
        FormDefTree formDefTree = formDefTreeDao.getByFormKey(formKey);
        if (BeanUtils.isNotEmpty(formDefTree)) {
            bpmFormDefXml.setFormDefTree(formDefTree);
        }
    }

    /**
     * 修改表单分类
     *
     * @param categoryId  分类id
     * @param formKeyList formKey集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void updCategory(String categoryId, List<String> formKeyList) {
        formDefDao.updCategory(categoryId, formKeyList);
    }

    /**
     * 导入xml
     *
     * <pre>
     * 1.导入流程定义
     * 2.导入流程定义权限
     * 3.导入数据模板
     * </pre>
     *
     * @param inputStream InputStream
     * @param tenantId    租户id
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public void importXml(InputStream inputStream, String tenantId) throws Exception {
        Document doc = Dom4jUtil.loadXml(inputStream);
        Element root = doc.getRootElement();
        // 验证格式是否正确
        this.checkXMLFormat(root);

        String xmlStr = root.asXML();
        BpmFormDefXmlList bpmFormDefXmlList = (BpmFormDefXmlList) XmlBeanUtil.unmarshall(xmlStr, BpmFormDefXmlList.class);
        List<BpmFormDefXml> list = bpmFormDefXmlList.getBpmFormDefXmlList();
        for (BpmFormDefXml bpmFormDefXml : list) {
            this.importBpmFormDef(bpmFormDefXml, tenantId);
        }
    }

    /**
     * 检查XML格式是否正确
     *
     * @param root Element
     * @throws Exception Exception
     */
    private void checkXMLFormat(Element root) throws Exception {
        String msg = localeMessageSource.getMessage("dataSource.importXml.formatError");
        if (!FormConstants.STR_FORM.equals(root.getName())) {
            throw new Exception(msg);
        }

        List<Element> itemLists = root.elements();
        for (Element elm : itemLists) {
            if (!FormConstants.STR_FORM_DEFS.equals(elm.getName())) {
                throw new Exception(msg);
            }
        }
    }

    /**
     * 导入表单信息
     *
     * @param bpmFormDefXml BpmFormDefXml
     * @param tenantId      租户id
     * @throws Exception 异常
     */
    public  Map<String, Map> importBpmFormDef(BpmFormDefXml bpmFormDefXml, String tenantId) throws Exception {
        Set<Identity> identitySet = new HashSet<>();
        // 导入自定义表
        Map map = this.importBpmFormTable(bpmFormDefXml.getBpmFormTableXml(), identitySet, tenantId);
        // 流水号
        formTableService.importIdentity(identitySet);
        //提取公共方法
        return this.importFormDef(bpmFormDefXml,map,tenantId);
    }

    /**
     * 导入流程时同时导入表单（避免tableId的丢失）
     *
     * @param bpmFormDefXml
     * @param tenantId
     * @return
     */
    public  Map<String, Map> importBpmFormDef(BpmFormDefXml bpmFormDefXml,String tabId, String tenantId) throws Exception {
        Map<String, String> map = new HashMap<>(1);
        map.put(tabId,tabId);
        return this.importFormDef(bpmFormDefXml,map,tenantId);
    }

    /**
     * 导入表单信息的公共方法
     * @param bpmFormDefXml
     * @param map
     * @param tenantId
     * @return
     */
    private Map<String, Map> importFormDef(BpmFormDefXml bpmFormDefXml,Map<String, String> map, String tenantId)throws Exception {
        FormDef bpmFormDef = bpmFormDefXml.getBpmFormDef();
        String origFormKey = bpmFormDef.getFormKey();
        String origformDefId= bpmFormDef.getFormDefId();
        //导入表单信息
        bpmFormDef = this.importBpmFormDef(bpmFormDef, map, tenantId);
        String formKey  = bpmFormDef.getFormKey();
        String formDefId= bpmFormDef.getFormDefId();

        //导入表单模板
        DataTemplate bpmDataTemplate = bpmFormDefXml.getBpmDataTemplate();
        if (BeanUtils.isNotEmpty(bpmDataTemplate)) {
            try{
                bpmDataTemplate.setTableId(bpmFormDef.getTableId());
                String templateHtml = dataTemplateService.generateTemplate(bpmDataTemplate);
                bpmDataTemplate.setTemplateHtml(templateHtml);
                this.importBpmDataTemplate(bpmDataTemplate, formKey);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        //表单权限
        List<FormRights> bpmFormRightsList = bpmFormDefXml.getBpmFormRightsList();
        if (BeanUtils.isNotEmpty(bpmFormRightsList)) {
            for (FormRights bpmFormRights : bpmFormRightsList) {
                this.importBpmFormRights(bpmFormRights, formKey);
            }
        }
        //业务保存设置
        SysBusEvent sysBusEvent = bpmFormDefXml.getSysBusEvent();
        if(BeanUtils.isNotEmpty(sysBusEvent)){
            this.importSysBusEvent(sysBusEvent,formKey);
        }
        //树结构设置
        FormDefTree defTree = bpmFormDefXml.getFormDefTree();
        if(BeanUtils.isNotEmpty(defTree)){
            this.importFormDefTree(defTree);
        }

        Map<String, Map> defMap = new HashMap<String, Map>(2);
        Map<String, String> keyMap = new HashMap<String, String>(1);
        Map idMap = new HashMap(1);

        idMap.put(origformDefId, formDefId);
        keyMap.put(origFormKey, formKey);
        defMap.put("id", idMap);
        defMap.put("key", keyMap);

        return defMap;
    }
    /**
     * 导入自定义表
     *
     * @param bpmFormTableXml BpmFormTableXml
     * @param identitySet     Set<Identity>
     * @throws Exception 异常
     */
    private Map<String, String> importBpmFormTable(BpmFormTableXml bpmFormTableXml, Set<Identity> identitySet, String tenantId) throws Exception {
        Map map = new HashMap(16);
        if (BeanUtils.isNotEmpty(bpmFormTableXml)) {
            map = formTableService.importBpmFormTableXml(bpmFormTableXml, tenantId);
            formTableService.setIdentity(bpmFormTableXml.getIdentityList(), identitySet);
        }
        return map;
    }

    /**
     * 导入的表单信息保存
     *
     * @param bpmFormDef 表单对象
     * @param map        Map<String, String>
     * @param tenantId   租户id
     * @return FormDef
     */
    private FormDef importBpmFormDef(FormDef bpmFormDef, Map<String, String> map, String tenantId)throws Exception {
        String formKey = bpmFormDef.getFormKey();
        Integer maxVersion = formDefDao.getMaxVersionByFormKey(formKey);
        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
        boolean isNameEqual = sysUser.getUserId().equals(bpmFormDef.getCreateBy());
        bpmFormDef.setHtml(StringUtil.convertScriptLine(bpmFormDef.getHtml(), false));
        bpmFormDef.setTemplate(StringUtil.convertScriptLine(bpmFormDef.getTemplate(), false));
        // 设置tableId
        this.setTableId(bpmFormDef, map);
        // 设置分类
        this.setCategoryId(bpmFormDef);

        bpmFormDef.setCreateTime(new Date());
        bpmFormDef.setCreateBy(sysUser.getUserId());
        bpmFormDef.setCreator(sysUser.getAccount());
        if(FormDef.IS_PUBLISHED.equals(bpmFormDef.getIsPublished())){
            bpmFormDef.setPublishTime(new Date());
            bpmFormDef.setPublishedBy(sysUser.getFullName());
        }
        //如果租户ID为空，则取当前用户的租户ID
        if (StringUtil.isEmpty(tenantId)) {
            tenantId = ContextUtil.getCurrentUserTenantId();
        }
        bpmFormDef.setTenantId(tenantId);
        if (BeanUtils.isEmpty(maxVersion) || maxVersion == FormConstants.DEFAULT_INT_ZERO) {
            bpmFormDef.setFormDefId(UUIDUtils.getUUIDFor32());
            bpmFormDef.setVersionNo(FormConstants.DEFAULT_INT_ONE);
            formDefDao.add(bpmFormDef);
            String formDefId = bpmFormDef.getFormDefId();
            sysTenantDynamicDataService.addSysTenantDynamicData(formDefId, tenantId, FormDef.class);
        } else {
            if(!isNameEqual){
                throw new Exception(localeMessageSource.getMessage("formDef.importXml.aliasRepeat"));
            }
            bpmFormDef.setFormDefId(UUIDUtils.getUUIDFor32());
            bpmFormDef.setVersionNo(maxVersion + FormConstants.DEFAULT_INT_ONE);
            bpmFormDef.setIsDefault(FormDef.IS_NOT_DEFAULT);
            formDefDao.add(bpmFormDef);
            String formDefId = bpmFormDef.getFormDefId();
            sysTenantDynamicDataService.addSysTenantDynamicData(formDefId, tenantId, FormDef.class);
        }
        return bpmFormDef;
    }

    /**
     * 设置表ID
     *
     * @param bpmFormDef FormDef
     * @param map        Map<String, String>
     */
    private void setTableId(FormDef bpmFormDef, Map<String, String> map) {
        if (BeanUtils.isEmpty(bpmFormDef.getTableId())) {
            return;
        }
        if (BeanUtils.isNotEmpty(map)) {
            String tableId = null;
            if (map.size() > 1) {
                tableId = map.get(FormConstants.DEFAULT_STR_ZERO);
            } else {
                tableId = map.keySet().iterator().next();
            }
            bpmFormDef.setTableId(tableId);
            /*FormTable bpmFormTable = formTableService.getOneById(tableId);
            if (BeanUtils.isEmpty(bpmFormTable)) {
                bpmFormDef.setTableId(null);
            } else {
                bpmFormDef.setTableId(tableId);
            }*/
        }
    }

    /**
     * 设置分类
     *
     * @param bpmFormDef FormDef
     */
    private void setCategoryId(FormDef bpmFormDef) {
        if (BeanUtils.isEmpty(bpmFormDef.getCategoryId())) {
            return;
        }
        GlobalType globalType = globalTypeDao.getById(bpmFormDef.getCategoryId());
        if (BeanUtils.isEmpty(globalType)) {
            bpmFormDef.setCategoryId(null);
        }
    }

    /**
     * 保存 数据模板
     *
     * @param bpmTableTemplate DataTemplate
     * @param formKey          表单别名
     */
    private void importBpmDataTemplate(DataTemplate bpmTableTemplate, String formKey) {
        DataTemplate tableTemplate = dataTemplateDao.getById(bpmTableTemplate.getId());
        if (BeanUtils.isNotEmpty(tableTemplate)) {
            dataTemplateDao.update(bpmTableTemplate);
        } else {
            bpmTableTemplate.setFormKey(formKey);
            bpmTableTemplate.setId(UUIDUtils.getUUIDFor32());
            dataTemplateDao.add(bpmTableTemplate);
        }
    }

    /**
     * 保存表单权限
     *
     * @param bpmFormRights FormRights
     * @param formKey       表单别名
     */
    private void importBpmFormRights(FormRights bpmFormRights, String formKey) {
        FormRights formRights = formRightsDao.getById(bpmFormRights.getId());
        if (BeanUtils.isNotEmpty(formRights)) {
            formRightsDao.update(bpmFormRights);
        } else {
            bpmFormRights.setFormKey(formKey);
            bpmFormRights.setId(UUIDUtils.getUUIDFor32());
            formRightsDao.add(bpmFormRights);
        }
    }

    /**
     * 保存业务设置
     *
     * @param sysBusEvent SysBusEvent
     * @param formKey     表单别名
     */
    private void importSysBusEvent(SysBusEvent sysBusEvent, String formKey) {
        SysBusEvent sysBusEventTemplet = sysBusEventDao.getById(sysBusEvent.getId());
        if (BeanUtils.isNotEmpty(sysBusEventTemplet)) {
            sysBusEventDao.update(sysBusEvent);
        } else {
            sysBusEventTemplet.setFormKey(formKey);
            sysBusEventTemplet.setId(UUIDUtils.getUUIDFor32());
            sysBusEventDao.add(sysBusEvent);
        }
    }

    /**
     * 保存表单树
     *
     * @param formDefTree FormDefTree
     */
    private void importFormDefTree(FormDefTree formDefTree) {
        FormDefTree defTree = formDefTreeDao.getById(formDefTree.getId());
        if (BeanUtils.isNotEmpty(defTree)) {
            formDefTreeDao.update(defTree);
        } else {
            defTree.setId(UUIDUtils.getUUIDFor32());
            formDefTreeDao.add(defTree);
        }
    }

    /**
     * 获得已发布版本数量
     *
     * @param formKey 表单别名
     */
    public int getCountByFormKey(String formKey) {
        return formDefDao.getCountByFormKey(formKey);
    }

    /**
     * 添加复制的表单，包括表单权限信息
     *
     * @param bpmFormDef FormDef
     * @param oldFormKey 原表单别名
     */
    @Transactional(rollbackFor = Exception.class)
    public void copyForm(FormDef bpmFormDef, String oldFormKey) {
        //保存，在bpm_form_def中增加一条数据
        formDefDao.add(bpmFormDef);
        sysTenantDynamicDataService.addSysTenantDynamicData(bpmFormDef.getFormDefId(), ContextUtil.getCurrentUserTenantId(), FormDef.class);
        //获得新表单的key
        String formKey = bpmFormDef.getFormKey();
        //设计类型(0,通过表生成，1，通过表单设计)，如果是通过表生成执行下面
        if (bpmFormDef.getDesignType() == 0) {
            //根据表单key获取表单权限。此表单必须已经在管理中配置了表单权限
            List<FormRights> list = formRightsDao.getByFormKeyNodeEmpty(oldFormKey);
            for (FormRights bpmFormRights : list) {
                bpmFormRights.setId(UUIDUtils.getUUIDFor32());
                bpmFormRights.setFormKey(formKey);
                formRightsDao.add(bpmFormRights);
            }
        }
    }

    /**
     * 自定义表单发布
     *
     * @param formDefId 自定义表单Id
     * @param fullName  发布人
     */
    @Transactional(rollbackFor = Exception.class)
    public void publish(String formDefId, String fullName) {
        // 设为已发布
        FormDef formDef = formDefDao.getById(formDefId);
        formDef.setIsPublished((short) FormConstants.DEFAULT_INT_ONE);
        formDef.setPublishedBy(fullName);
        formDef.setPublishTime(new Date());
        formDefDao.update(formDef);
    }

    /**
     * 增加表单定义。
     *
     * @param formDef 自定义表单对象
     */
    @Transactional(rollbackFor = Exception.class)
    public String addForm(FormDef formDef) {
        String id = UUIDUtils.getUUIDFor32();
        this.setFormDefParam(formDef, id, FormDef.IS_DEFAULT, FormDef.VERSION_NO_DEFAULT);
        formDefDao.add(formDef);
        String tenantId = ContextUtil.getCurrentUserTenantId();
        //在动态数据表中添加表单信息
        sysTenantDynamicDataService.addSysTenantDynamicData(id, tenantId, FormDef.class);
        historyDataService.addSysHistoryData(SysHistoryData.SYS_FORM_DEF_TEMPLATE, formDef.getSubject(),
                formDef.getHtml(), formDef.getFormDefId());
        return id;
    }

    /**
     * 新增和新建版本时，对表单数据的一些初始化设置
     * 共有属性，都设为不公开，发布人为空
     *
     * @param formDef   表单对象
     * @param formDefId 表单id
     * @param isDefault 是否默认
     * @param versionNo 版本号
     */
    private void setFormDefParam(FormDef formDef, String formDefId, Short isDefault, Integer versionNo) {
        formDef.setFormDefId(formDefId);
        formDef.setIsDefault(isDefault);
        formDef.setVersionNo(versionNo);
        formDef.setIsPublished(FormDef.IS_NOT_PUBLISHED);
        formDef.setPublishedBy("");
    }


    /**
     * 更新表单及权限
     *
     * @param formDef 自定义表单对象
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateForm(FormDef formDef) {
        formDefDao.update(formDef);
        historyDataService.addSysHistoryData(SysHistoryData.SYS_FORM_DEF_TEMPLATE, formDef.getSubject(),
                formDef.getHtml(), formDef.getFormDefId());
    }

    /**
     * 根据表单定义id创建新的表单版本。
     *
     * @param formDefId    原始表单定义ID
     * @param newFormDefId 新自定义表单Id
     */
    @Transactional(rollbackFor = Exception.class)
    public void newVersion(String formDefId, String newFormDefId) {
        //根据表单id获取表单信息
        FormDef formDef = formDefDao.getById(formDefId);
        //根据表单的key值获取当前表单的最大版本
        Integer maxVersion = formDefDao.getMaxVersionByFormKey(formDef.getFormKey());
        //创建新版本
        FormDef newVersion = new FormDef();
        BeanCopyUtil.copyBean(formDef, newVersion);
        this.setFormDefParam(newVersion, newFormDefId, FormDef.IS_NOT_DEFAULT, maxVersion + 1);
        formDefDao.add(newVersion);
        String tenantId = ContextUtil.getCurrentUserTenantId();
        sysTenantDynamicDataService.addSysTenantDynamicData(newFormDefId, tenantId, FormDef.class);
    }

    /**
     * 根据formKey查询对应表单
     *
     * @param formKey 表单别名
     * @return List<FormDef>
     */
    public List<FormDef> getByFormKey(String formKey) {
        return formDefDao.getByFormKeyIsDefault(formKey, null);
    }


    /**
     * 判断表单是否已经被流程使用
     *
     * @param formKey 表单key
     * @return 记录条数
     */
    public int getFlowUsed(String formKey) {
        return formDefDao.getFlowUsed(formKey);
    }

    /**
     * 根据表单别名 获得默认版本
     *
     * @param formKey 表单别名
     * @return FormDef
     */
    public FormDef getDefaultVersionByFormKey(String formKey) {
        return formDefDao.getDefaultVersionByFormKey(formKey);
    }

    /**
     * 删除多个表单
     *
     * @param aryFormKey 表单key数组
     * @return 已经关联流程的表单集合
     */
    public List<String> delByFormKeys(String[] aryFormKey) throws Exception {
        List<String> bindFlowFormList = new ArrayList<>();
        for (String formKey : aryFormKey) {
            int bindFlowCount = getFlowUsed(formKey);
            if (bindFlowCount > 0) {
                bindFlowFormList.add(formKey);
            } else {
                List<FormDef> list = getByFormKey(formKey);
                //根据formKey删除表单中数据
                delByFormKey(list, formKey);
            }
        }
        return bindFlowFormList;
    }

    /**
     * 根据表单别名删除数据 如果表已经生成并且表单是通过设计器进行设计的那么将删除所创建的表
     *
     * @param list    表单集合
     * @param formKey 表单别名
     * @throws SQLException
     */
    @Transactional(rollbackFor = Exception.class)
    public void delByFormKey(List<FormDef> list, String formKey) throws SQLException {
        //删除映射表中数据
        for (FormDef def : list) {
            sysTenantDynamicDataService.delByDataId(def.getFormDefId());
        }
        FormDef formDef = formDefDao.getDefaultVersionByFormKey(formKey);
        String tableId = formDef.getTableId();
        // 删除表单权限
        formRightsService.delByFormKey(formKey, true, PlatformType.PC);
        // 先删除表单，后判断是否还有表单使用该表
        formDefDao.delByFormKey(formKey);
        // 删除数据模版。
        dataTemplateDao.delByFormKey(formKey);
        // tableId不为空并且由表单生成
        if (StringUtil.isNotEmpty(tableId) && formDef.getDesignType() == FormDef.DESIGN_TYPE_CUSTOM_DESIGN) {
            FormTable formTable = formTableService.getOneById(tableId);
            // 是否还有表单使用该表
            int tableHasForm = formDefDao.isTableBindForm(tableId);
            if (formTable != null && tableHasForm <= 0) {
                formTableService.dropTable(formTable);
                formTableService.delTable(formTable);
            }
        }
        // 删除树结构设置
        formDefTreeDao.delByFormDefKey(formDef.getFormKey());
    }

    /**
     * 修改表单的默认版本
     *
     * @param formDefId formDefId
     */
    @Transactional(rollbackFor = Exception.class)
    public void setDefaultVersion(String formDefId) {
        FormDef formDef = formDefDao.getById(formDefId);
        //获取原来的默认版本并修改为非默认
        FormDef oldDefaultFormDef = formDefDao.getDefaultVersionByFormKey(formDef.getFormKey());
        oldDefaultFormDef.setIsDefault(FormDef.IS_NOT_DEFAULT);
        formDefDao.update(oldDefaultFormDef);
        //设置当前版本为默认
        formDef.setIsDefault(FormDef.IS_DEFAULT);
        formDefDao.update(formDef);
    }

    /**
     * 设置表单是否公开
     *
     * @param formDefId 表单id
     * @param isPublic  是否公开属性
     */
    @Transactional(rollbackFor = Exception.class)
    public void setPublic(String formDefId, Short isPublic) {
        FormDef formDef = formDefDao.getById(formDefId);
        formDef.setIsPublic(isPublic);
        formDefDao.update(formDef);
    }

    /**
     * 根据表单key获取默认的表单定义。
     *
     * @param formKey
     * @return FormDef
     */
    public FormDef getDefaultPublishedByFormKey(String formKey) {
        return formDefDao.getDefaultPublishedByFormKey(formKey);
    }

    /**
     * 根据流程定义ID，节点ID，取得流程开始表单定义。 在节点没有设置表单时，如果cascade为true，则会查询全局表单和开始表单
     *
     * @param actDefId
     * @param nodeId
     * @param cascade  是否向上查找标志
     * @return
     */
    public FormDef getNodeFormDef(String actDefId, String nodeId, boolean cascade) {
        List<FormDef> defList = formDefDao.getByActDefIdAndNodeId(actDefId, nodeId);
        if (BeanUtils.isNotEmpty(defList)) {
            return defList.get(0);
        }
        if (!cascade) {
            return null;
        }
        FormDef def = this.getGlobalFormDef(actDefId);
        if (def != null) {
            return def;
        }
        return def;
    }

    /**
     * 根据流程定义ID，取得流程全局表单定义
     *
     * @param actDefId
     * @return
     */
    public FormDef getGlobalFormDef(String actDefId) {
        List<FormDef> defList = formDefDao.getByActDefIdAndSetType(actDefId, BpmNodeSet.SETTYPE_GLOABLEFORM);
        if (BeanUtils.isNotEmpty(defList)) {
            return defList.get(0);
        } else {
            return null;
        }
    }

    /**
     * 根据表单别名查询表是否版本控制
     *
     * @param formKey 表单别名
     * @return 表版本控制 needVer
     */
    public Integer getNeedVerByFormKey(String formKey) {
        return formDefDao.getNeedVerByFormKey(formKey);
    }

    /**
     * 根据 formDef 获取表单编辑相关数据，不同地方可能需要不同的数据，利用传入的map参数可以进行扩展
     *
     * @param formDef formDef
     * @param retMap  retMap
     * @return retMap
     */
    public Map<String, Object> getEditDataByFormDef(FormDef formDef, Map<String, Object> retMap) {
        String mainTableId = formDef.getTableId();
        List<FormTable> subTableList = formTableService.getSubTableByMainTableId(mainTableId);
        String[] tableIds = new String[subTableList.size() + 1];
        tableIds[0] = mainTableId;
        for (int i = 0; i < subTableList.size(); i++) {
            String tableId = subTableList.get(i).getTableId();
            tableIds[i + 1] = tableId;
        }
        Map<String, Object> mainTableMap = new HashMap<>(16);
        for (int i = 0; i < tableIds.length; i++) {
            FormTable table = formTableService.getOneById(tableIds[i]);
            List<FormField> fields = formFieldService.getByTableId(tableIds[i]);
            if (table.getIsMain() == FormTable.IS_MAIN) {
                mainTableMap.put("tableName", table.getTableName());
                mainTableMap.put("tableId", table.getTableId());
                mainTableMap.put("tableFields", fields);
                mainTableMap.put("templateAlias", "4");
                retMap.put("mainTable", mainTableMap);
            } else {//子表
                if (StringUtil.isNotEmpty(formDef.getSubTemplateField())) {
                    JSONArray jsonArray = JSONArray.fromObject(formDef.getSubTemplateField());
                    for (int j = 0; j < jsonArray.size(); j++) {
                        JSONObject field = JSONObject.fromObject(jsonArray.get(j));
                        String subTableId = field.get("subTableId").toString();
                        String listDisplay = field.get("listDisplay").toString();
                        String dialogDisplay = field.get("dialogDisplay").toString();
                        if (tableIds[i].equals(subTableId)) {
                            for (FormField formField : fields) {
                                String filedName = formField.getFieldName() + ",";
                                formField.setListShow(FormField.LIST_SHOW_FALSE);
                                formField.setDialogShow(FormField.DIALOG_SHOW_FALSE);
                                if (listDisplay.contains(filedName)) {
                                    formField.setListShow(FormField.LIST_SHOW_TRUE);
                                }
                                if (dialogDisplay.contains(filedName)) {
                                    formField.setDialogShow(FormField.DIALOG_SHOW_TRUE);
                                }
                            }
                        }
                    }
                }
                Map<String, Object> subTableMap = new HashMap<>(16);
                subTableMap.put("tableName", table.getTableName());
                subTableMap.put("tableId", table.getTableId());
                subTableMap.put("tableFields", fields);
                subTableMap.put("templateAlias", "2");
                retMap.put("subTable" + i, subTableMap);
            }
        }
        retMap.put("subCount", tableIds.length - 1);
        //主子表模板
        retMap.put("templatesId", formDef.getTemplatesId());
        return retMap;
    }

    /**
     * 根据流程定义ID，获取Table ID
     *
     * @param id
     * @return
     */
    public String getTableIdByModelId(String id) {
        List<FormDef> formDefList = formDefDao.queryByProcDefId(id);
        if (BeanUtils.isNotEmpty(formDefList)) {
            return formDefList.get(0).getTableId();
        } else {
            return null;
        }
    }
    /**
     * 处理权限的人员
     *
     * @param permission
     * @param flag   标记是导出（true）还是导入(false)
     * @return
     */
    public String parsePermission(String permission, boolean flag) {
        JSONObject json = JSONObject.fromObject(permission);
        Object read = json.get("read");
        Object write = json.get("write");
        if (read == null){  read = "{}";    }
        if (write == null){ write = "{}";   }
        json.element("read", parseUseInfo(read.toString(), flag));
        json.element("write", parseUseInfo(write.toString(), flag));
        return json.toString();
    }

    /**
     * 处理权限的人员
     *
     * @param mode  处理json
     * @param flag  标记是导出（true）还是导入(false)
     * @return
     */
    private String parseUseInfo(String mode, boolean flag) {
        JSONObject node = JSONObject.fromObject(mode);
        if (JSONUtils.isNull(node)){            return "";  }
        if (JSONUtils.isNull(node.get("type"))){return mode;}
        if (JSONUtils.isNull(node.get("id"))){  return mode;}

        String type = node.get("type").toString();
        String id = (String) node.get("id");
        String tempFullName = (String) node.get("fullName");
        if (FormRights.TYPE_NONE.equals(type) || FormRights.TYPE_EVERYONE.equals(type)) {
            return mode;
        }
        if (flag) {// 导出只对人员处理
            if (FormRights.TYPE_USER.equals(type)) {
                SysUser sysUser = (SysUser) sysUserDao.getById(Long.parseLong(id));
                if (BeanUtils.isNotEmpty(sysUser)) {
                    node.element("fullName", sysUser.getAccount());
                }
            }
        }
        // 导入
        else {
            if (StringUtil.isEmpty(tempFullName)) {
                return cleanPermission(node);
            }
            // 因传入的fullName可能为“用户1,用户2”，因此将传入的fullName进行分割再处理
            String[] fullNameArr = tempFullName.split(",");
            // 用于统计找不到记录的次数
            int count = 0;
            // 存放过滤后的用户ID
            StringBuffer ids = new StringBuffer();
            // 存放过滤后的用户工号
            StringBuffer names = new StringBuffer();

            for (String fullName : fullNameArr) {
                // 用户
                if (FormRights.TYPE_USER.equals(type)) {
                    SysUser sysUser = (SysUser) sysUserDao.getByAccount(fullName);
                    if (BeanUtils.isEmpty(sysUser)) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的用户工号：" + fullName + ",不存在!请检查!");
                        count++;
                    } else {
                        ids.append(sysUser.getUserId()).append(",");
                        names.append(sysUser.getFullName()).append(",");

                    }
                }
                // 角色
                else if (FormRights.TYPE_ROLE.equals(type)) {
                    List<SysRole> sysRoleList = sysRoleDao.queryByRoleName(fullName);
                    if (BeanUtils.isEmpty(sysRoleList)) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的角色名称：" + fullName + ",不存在!请检查!");
                        count++;
                    } else if (sysRoleList.size() > 1) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的角色名称：" + fullName + ",多于一条记录!请检查!");
                        count++;
                    } else {
                        SysRole sysRole = (SysRole) sysRoleList.get(0);
                        ids.append(sysRole.getRoleId()).append(",");
                        names.append(sysRole.getRoleName()).append(",");
                    }
                }
                // 组织或组织负责人
                else if (FormRights.TYPE_ORG.equals(type) || FormRights.TYPE_ORGMGR.equals(type)) {
                    List<SysOrg> sysOrgList = sysOrgDao.queryByOrgName(fullName);
                    if (BeanUtils.isEmpty(sysOrgList)) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的组织名称：" + fullName + ",不存在!请检查!");
                        count++;
                    } else if (sysOrgList.size() > 1) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的组织名称：" + fullName + ",多于一条记录!请检查!");
                        count++;
                    } else {
                        SysOrg sysOrg = (SysOrg) sysOrgList.get(0);
                        ids.append(sysOrg.getOrgId()).append(",");
                        names.append(sysOrg.getOrgName()).append(",");
                    }
                }
                // 岗位
                else if (FormRights.TYPE_POS.equals(type)) {
                    List<Position> positionList = positionDao.queryByPosName(fullName);
                    if (BeanUtils.isEmpty(positionList)) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的岗位名称：" + fullName + ",不存在!请检查!");
                        count++;
                    } else if (positionList.size() > 1) {
                        MsgUtil.addMsg(MsgUtil.ERROR, "表单权限的中的岗位名称：" + fullName + ",多于一条记录!请检查!");
                        count++;
                    } else {
                        Position position = positionList.get(0);
                        ids.append(position.getPosId()).append(",");
                        names.append(position.getPosName()).append(",");
                    }
                }
            }
            // 若数组中所有的名称在数据库中都无对应记录
            if (count == fullNameArr.length) {
                return cleanPermission(node);
            } else {
                node.element("id", ids.deleteCharAt(ids.length() - 1).toString());
                node.element("fullName", names.deleteCharAt(names.length() - 1).toString());
            }
        }
        return node.toString();
    }

    /**
     * 清理权限
     *
     * @param node  权限
     * @return
     */
    private String cleanPermission(JSONObject node) {
        node.element("id", "");
        node.element("fullName", "");
        return node.toString();
    }

    public Map<String, Boolean> getDefaultExportMap(Map<String, Boolean> map) {
        if (BeanUtils.isEmpty(map)) {
            map = new HashMap<String, Boolean>(6);
            //TODO bpmFormDef==formDefs ???
            map.put("bpmFormDef", true);
            // 导出对应的表 bpmFormTable
            map.put(FormConstants.STR_BPM_FORM_TABLE, false);
            // 导出自定义表单 非默认版本 bpmFormDefOther
            map.put(FormConstants.STR_FORM_DEF_OTHER,true);
            // 数据模板 bpmTableTemplate
            map.put(FormConstants.STR_TABLE_TEMPLATE,true);
            // 表单权限 bpmFormRights
            map.put(FormConstants.STR_FORM_RIGHTS,   true);
            //业务数据
            map.put(FormConstants.STR_SYS_BUS_EVENT, true);
            //表单树形配置 formDefTree
            map.put(FormConstants.STR_FORM_DEF_TREE, true);
        }
        return map;
    }

    /**
     * 获取表单对应表的新tableId
     *
     * @param bpmFormTableXmlList
     * @param bpmFormDefXml
     * @return
     */
    public String getTableIdByFormDefFormTable(List<BpmFormTableXml> bpmFormTableXmlList, BpmFormDefXml bpmFormDefXml) {
        for(BpmFormTableXml tableXml:bpmFormTableXmlList){
            if(tableXml.getBpmFormTable().getIsMain().shortValue()==FormTable.IS_MAIN){
                FormTable formTable = formTableService.getByTableName(tableXml.getBpmFormTable().getTableName());
                return (BeanUtils.isNotEmpty(formTable)?formTable.getTableId():null);
            }
        }
        return null;
    }
}